"""
订单审计与库存快照写入 MongoDB
"""
from __future__ import annotations

import logging
from datetime import datetime
from decimal import Decimal
from typing import Any, Dict, Optional

from pymongo.errors import PyMongoError

from config.settings import settings
from database.mongo_client import get_collection

logger = logging.getLogger("order_audit")
_index_initialized = False


def _sanitize(value: Any) -> Any:
    """将 Decimal 等不可序列化类型转换为基础类型"""
    if isinstance(value, Decimal):
        return float(value)
    if isinstance(value, dict):
        return {k: _sanitize(v) for k, v in value.items()}
    if isinstance(value, (list, tuple)):
        return [_sanitize(v) for v in value]
    return value


def _ensure_indexes():
    """初始化集合索引（只执行一次）"""
    global _index_initialized
    if _index_initialized:
        return
    try:
        audit_col = get_collection(settings.ORDER_AUDIT_COLLECTION)
        audit_col.create_index([("order_no", 1), ("created_at", -1)])
        audit_col.create_index([("event_type", 1), ("created_at", -1)])

        snapshot_col = get_collection(settings.INVENTORY_SNAPSHOT_COLLECTION)
        snapshot_col.create_index([("goods_id", 1), ("created_at", -1)])
        snapshot_col.create_index([("order_no", 1), ("created_at", -1)])
    except PyMongoError as exc:
        logger.error("初始化 MongoDB 索引失败: %s", exc)
    else:
        _index_initialized = True


def log_order_event(
    order_no: Optional[str],
    event_type: str,
    *,
    status: Optional[str] = None,
    message: Optional[str] = None,
    payload: Optional[Dict[str, Any]] = None,
    metadata: Optional[Dict[str, Any]] = None,
):
    """记录订单流转事件"""
    if not order_no:
        order_no = "unknown"
    _ensure_indexes()
    doc = {
        "order_no": order_no,
        "event_type": event_type,
        "status": status,
        "message": message,
        "payload": _sanitize(payload) if payload else None,
        "metadata": _sanitize(metadata) if metadata else None,
        "created_at": datetime.utcnow(),
    }
    # 移除值为 None 的字段，减少存储
    doc = {k: v for k, v in doc.items() if v is not None}
    try:
        get_collection(settings.ORDER_AUDIT_COLLECTION).insert_one(doc)
    except PyMongoError as exc:
        logger.error("记录订单审计事件失败: order_no=%s event=%s err=%s", order_no, event_type, exc)


def log_inventory_snapshot(
    *,
    goods_id: Optional[int],
    action: str,
    order_no: Optional[str] = None,
    stock_before: Optional[int] = None,
    stock_after: Optional[int] = None,
    change: Optional[int] = None,
    source: Optional[str] = None,
    metadata: Optional[Dict[str, Any]] = None,
):
    """记录库存快照"""
    _ensure_indexes()
    doc = {
        "goods_id": goods_id,
        "action": action,
        "order_no": order_no,
        "stock_before": stock_before,
        "stock_after": stock_after,
        "change": change,
        "source": source,
        "metadata": _sanitize(metadata) if metadata else None,
        "created_at": datetime.utcnow(),
    }
    doc = {k: v for k, v in doc.items() if v is not None}
    try:
        get_collection(settings.INVENTORY_SNAPSHOT_COLLECTION).insert_one(doc)
    except PyMongoError as exc:
        logger.error(
            "记录库存快照失败: goods_id=%s action=%s order_no=%s err=%s",
            goods_id,
            action,
            order_no,
            exc,
        )

